/* 
 * File:   TreeGenerator.h
 * Author: jcrada
 *
 * Created on April 7, 2009, 8:28 PM
 */

#ifndef _TREEGENERATOR_H
#define	_TREEGENERATOR_H


#include "TreeOfNodes.h"
#include "RandomNode.h"
#include "IdNode.h"


namespace jcrada {

    class TreeGenerator {
    public:

        enum eMethod {
            M_FULL = 0, M_GROW, M_RAMPED, M_COUNT
        };

    private:
        int _functions_arity;
        double _min_terminal_value;
        double _max_terminal_value;
        eMethod _preferred_method;
        int _preferred_depth;
        RandomNode* _random_node;
        RandomGsl* _random_method;
        RandomGsl* _random_id;
        RandomGsl* _random_arity;

    protected:

        virtual RandomGsl& getRandomId() const {
            return *this->_random_id;
        }

        virtual RandomGsl& getRandomArity() const {
            return *this->_random_arity;
        }

        static void copyAndRemove(IdNode** nodes, int number_of_nodes, std::vector<IdNode*>& result);
        static void createAllSubtreeForN4(std::vector<IdNode*>& result);
        static void createAllSubtreeForN5(std::vector<IdNode*>& result);
        static void createAllSubtreeForN6(std::vector<IdNode*>& result);

    public:
        TreeGenerator();
        virtual ~TreeGenerator();

        virtual Node* createRandomSubtree();
        virtual Node* createRandomSubtree(int depth);
        virtual Node* createRandomSubtree(int depth, eMethod method);
        virtual TreeOfNodes* createRandomTree();
        virtual TreeOfNodes* createRandomTree(int depth);
        virtual TreeOfNodes* createRandomTree(int depth, eMethod method);

        virtual void createRandomIdSubtree(IdNode& parent, int* size, int max_arity, std::vector<int>& ids);
        virtual IdNode * createRandomIdSubtree(int size, int starting_id);
        virtual TreeOfNodes* createRandomIdTree(int size, int starting_id);

        static void createBinarySubtree(int size, Node** nodes);

        IdNode * createRandomIdSubtree(int max_arity, int size, std::vector<int>& ids);

        static void createAllSubtrees(int number_of_nodes, std::vector<IdNode*>& result);
        static std::vector<TreeOfNodes*>* createAllTrees(int number_of_nodes);
        static void tmp(int size);
        static int main(int argc, char** argv);

        virtual void setFunctionsArity(int arity) {
            this->_functions_arity = arity;
        }

        virtual int getFunctionsArity() const {
            return this->_functions_arity;
        }

        virtual void setMinTerminalValue(double min) {
            this->_min_terminal_value = min;
        }

        virtual double getMinTerminalValue() const {
            return this->_min_terminal_value;
        }

        virtual void setMaxTerminalValue(double max) {
            this->_max_terminal_value = max;
        }

        virtual double getMaxTerminalValue() const {
            return this->_max_terminal_value;
        }

        virtual void setPreferredMethod(eMethod method) {
            this->_preferred_method = method;
        }

        virtual eMethod getPreferredMethod() const {
            return this->_preferred_method;
        }

        virtual void setPreferredDepth(int depth) {
            this->_preferred_depth = depth;
        }

        virtual int getPreferredDepth() const {
            return this->_preferred_depth;
        }

        virtual RandomNode & getRandomNode() const {
            return *this->_random_node;
        }

        virtual RandomGsl & getRandomMethod() const {
            return *this->_random_method;
        }
    };
}

#endif	/* _TREEGENERATOR_H */

